package com.hp.bon.sgw.service;

import org.dom4j.Element;
import org.dom4j.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.bean.AuthResult;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.util.dcc.DccAvpHelper;
import com.hp.ocs.diameter.message.AVP;
import com.hp.ocs.diameter.message.DictionaryManager;
import com.hp.ocs.diameter.message.Message;

public class ReplaceDomainByAccNbrService{

	private static final Logger logger = LoggerFactory.getLogger(ReplaceDomainByAccNbrService.class);
	
	private static ReplaceDomainByAccNbrService instance;

	public static ReplaceDomainByAccNbrService getInstance() {
		if (instance == null) {
			return new ReplaceDomainByAccNbrService();
		}
		return instance;
	}
	
	private ReplaceDomainByAccNbrService()
	{
		
	}
	
	
	public AuthResult replaceDomain(CallParam callParam)
	{		
		AuthResult result = null;
		String serviceContextId = callParam.getServiceContextId();
		String sessionId = callParam.getSessionId();
		
		if (callParam.getRequest() instanceof Message) 
		{
			result = this.doQuery((Message) callParam.getRequest());
		} 
		else if (callParam.getRequest() instanceof XmlMessage) 
		{
			result = this.doQuery(((XmlMessage) callParam.getRequest()).getDataElement());
		}
		if (result.getCode() == Constants.ResultCode.SUCCESS) 
		{
			if(result.getHint()!=null)
			{
				String srcArea = DccAvpHelper.getArea(serviceContextId);
				String destArea = result.getHint();	
				if(destArea.length()==1) destArea = "00"+destArea;
				else if(destArea.length()==2) destArea = "0"+destArea;				
				logger.info(sessionId + " need to replace domain "+srcArea+" with " + destArea);
				String newSrvCtxID = serviceContextId.replaceAll("@"+srcArea, "@"+destArea);
				String newDestinationRealm = DccAvpHelper.getRealmPart(newSrvCtxID);
				callParam.setServiceContextId(newSrvCtxID);
				if (callParam.getRequest() instanceof Message) 
				{
					Message request = (Message)callParam.getRequest();
					DccAvpHelper.replaceSrvCtxID(request, newSrvCtxID);
					DccAvpHelper.replaceDestinationRealm(request, newDestinationRealm);
				}
				else if (callParam.getRequest() instanceof XmlMessage) 
				{			
					XmlMessage request = (XmlMessage)callParam.getRequest();					
					request.setSCID(newSrvCtxID);
				}		
			}
		}
		return result;
	}
	
	private AuthResult doQuery(Message msg)
	{				
		String errMsg = "";
		int areaCode = -1;
		try {			
			DictionaryManager _dic = DictionaryManager.getInstance();
			AVP accNbrAvp = msg.findAvpByNamePath("Service_Information/VC_Information/Destination_Account");
			String accNbrValue = "";
			
			if (accNbrAvp == null) {
				errMsg = "Cannot find Destination_Account AVP";
				logger.warn(errMsg);
				return new AuthResult(Constants.ResultCode.HomeQuery_ACC_Error, errMsg);
			}
			accNbrValue = _dic.getAvpValueAsString(accNbrAvp);
			if (accNbrValue.length() < 7) {
				errMsg = "Destination_Account is NOT vaild :" + accNbrValue;
				logger.warn(errMsg);
				return new AuthResult(Constants.ResultCode.HomeQuery_ACC_Error, errMsg);
			}
			String nbrStr = accNbrValue.substring(0, 7);
			
			if(confSrv.tpHcodes99Map!=null && confSrv.tpHcodes99Map.get(nbrStr)!=null)
			{
				areaCode = confSrv.tpHcodes99Map.get(nbrStr).getAreaCode();
			}
			else
			{				
				return new AuthResult(Constants.ResultCode.SUCCESS, null);
			}			
		} 
		catch (Exception e) {
			errMsg = "Destination_Account exception:"+e.getMessage();
			logger.warn(errMsg);
			return new AuthResult(Constants.ResultCode.HomeQuery_ACC_Error, errMsg);
		}
		return new AuthResult(Constants.ResultCode.SUCCESS, ""+areaCode);		
	}
	
	
	private AuthResult doQuery(Element reqData) {
		String errMsg = "";
		int areaCode = -1;		
		try {
			Node accNbrNode = reqData.selectSingleNode("VC_Information/Destination_Account");
			String accNbrValue = "";
			
			if (accNbrNode != null) {
				accNbrValue = accNbrNode.getText().trim();
			} else {
				errMsg = "Cannot find VC_Information/Destination_Account tag";
				logger.warn(errMsg);
				return new AuthResult(Constants.ResultCode.HomeQuery_ACC_Error, errMsg);
			}
			if (accNbrValue.length() < 7) {
				errMsg = "Destination_Account is NOT vaild :" + accNbrValue;
				logger.warn(errMsg);
				return new AuthResult(Constants.ResultCode.HomeQuery_ACC_Error, errMsg);
			}
			String nbrStr = accNbrValue.substring(0, 7);
			
			if(confSrv.tpHcodes99Map!=null && confSrv.tpHcodes99Map.get(nbrStr)!=null)
			{
				areaCode = confSrv.tpHcodes99Map.get(nbrStr).getAreaCode();
			}
			else
			{
//				errMsg = "Cannot find Destination_Account area code: " + accNbrValue;
//				logger.warn(errMsg);
//				return new AuthResult(Constants.ResultCode.HomeQuery_FAILED, errMsg);
				return new AuthResult(Constants.ResultCode.SUCCESS, null);
			}			
		} 
		catch (Exception e) {
			errMsg = "Destination_Account exception:"+e.getMessage();
			logger.warn(errMsg);
			return new AuthResult(Constants.ResultCode.HomeQuery_ACC_Error, errMsg);
		}
		return new AuthResult(Constants.ResultCode.SUCCESS, ""+areaCode);
	}
	
	private ConfigService confSrv;
	@Autowired
	public void setConfSrv(ConfigService confSrv) {
		this.confSrv = confSrv;
	}

}
